<?php

namespace app\services;

use app\traits\Page;
use plugin\admin\app\model\Subject;
use plugin\admin\app\model\SubjectCategory;
use plugin\admin\app\model\SubjectComment;
use plugin\admin\app\model\SubjectImage;
use plugin\admin\app\model\SubjectLike;
use plugin\admin\app\model\SubjectReply;
use plugin\admin\app\model\User;
use plugin\admin\app\model\UserLevel;
use support\Db;

class SubjectService
{
    public static function create($data)
    {
        $category = SubjectCategory::where('id', $data['category_id'])->first();

        if (!$category) {
            throw new \Exception('不存在的分类');
        }

        $isEnable = 1;
        if ($category['need_audit']) {
            $isEnable = 0;
        }

        $subjectId = Subject::insertGetId([
            'category_id' => $data['category_id'],
            'user_id' => get_user_id(),
            'title' => $data['title'],
            'content' => $data['content'],
            'comment_count' => 0,
            'good_count' => 0,
            'is_enable' => $isEnable,
            'created_time' => date('Y-m-d H:i:s'),
        ]);

        $imageData = [];
        foreach ($data['thumbs'] ?? [] as $thumb) {
            $imageData[] = [
                'subject_id' => $subjectId,
                'img_url' => $thumb
            ];
        }

        if ($imageData) {
            SubjectImage::insert($imageData);
        }

        return $isEnable;
    }

    public static function categories()
    {
        return SubjectCategory::select(['id', 'name'])->get()->toArray();
    }

    public static function list($page, $length, $id = 0, $self = false)
    {
        $offset = ($page - 1) * $length;
        $query = Subject::select(['id', 'user_id', 'title', 'content', 'is_enable', 'created_time', 'good_count', 'comment_count']);

        if ($id) {
            $query = $query->where('category_id', $id);
        }

        if ($self) {
            $query = $query->where('user_id', get_user_id());
        } else {
            $query = $query->where('is_enable', 1);
        }

        $count = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->orderByDesc('created_time')->get()->toArray();

        $userIds = array_column($list, 'user_id');
        $subjectIds = array_column($list, 'id');

        $users = User::select(['id', 'nickname', 'avatar'])->whereIn('id', $userIds)->get()->toArray();
        $users = array_combine(
            array_column($users, 'id'),
            array_values($users)
        );

        $subjectImages = SubjectImage::select(['subject_id', 'img_url'])->whereIn('subject_id', $subjectIds)->get()->toArray();

        $subjectLikes = SubjectLike::whereIn('subject_id', $subjectIds)->where('user_id', get_user_id())->get()->toArray();
        $subjectLikes = array_combine(
            array_column($subjectLikes, 'subject_id'),
            array_values($subjectLikes)
        );

        foreach ($list as $key=>$item) {
            $list[$key]['user_info'] = $users[$item['user_id']];
            foreach ($subjectImages as $image) {
                if ($item['id'] == $image['subject_id']) {
                    $list[$key]['images'][] = $image;
                }
            }

            $list[$key]['is_like'] = isset($subjectLikes[$item['id']]);
        }

        return Page::wrap($count, $page, $length, $list);
    }

    public static function detail($subjectId)
    {
        $subject = Subject::select(['id', 'user_id', 'title', 'content', 'created_time', 'good_count', 'comment_count'])->where('is_enable', 1)->where("id", $subjectId)->first();

        if (!$subject) {
            throw new \Exception('不存在的项目');
        }

        $user = User::select(['id', 'nickname', 'avatar'])->where('id', $subject['user_id'])->first()->toArray();

        $subjectImages = SubjectImage::select(['img_url'])->where('subject_id', $subject['id'])->get()->toArray();

        foreach ($subjectImages as $key=>$image) {
            $subjectImages[$key]['img_url'] = full_url($image['img_url']);
        }

        $like = SubjectLike::where('user_id', get_user_id())->where('subject_id', $subject['id'])->first();

        $subject['user_info'] = $user;
        $subject['images'] = $subjectImages;
        $subject['is_like'] = !is_null($like);

        return $subject;
    }

    public static function delete($subjectId)
    {
        $subject = Subject::where('id', $subjectId)->where('user_id', get_user_id())->first();

        if (!$subject) {
            throw new \Exception('不存在的话题');
        }

        $subject->delete();

        SubjectLike::where('subject_id', $subject['id'])->delete();

        SubjectImage::where('subject_id', $subject['id'])->delete();

        $comments = SubjectComment::where('subject_id', $subject['id'])->get()->toArray();

        $commentIds = array_column($comments, 'id');

        SubjectReply::whereIn('comment_id', $commentIds)->delete();
    }

    public static function comment($subjectId, $content)
    {
        SubjectComment::insert([
            'user_id' => get_user_id(),
            'subject_id' => $subjectId,
            'content' => $content,
            'created_time' => date('Y-m-d H:i:s')
        ]);

        Subject::where('id', $subjectId)->increment('comment_count');
    }

    public static function commentList($page, $length, $subjectId)
    {
        $offset = ($page - 1) * $length;
        $query = SubjectComment::where('subject_id', $subjectId);

        $count = (clone $query)->count();
        $list = $query->select(['id', 'user_id', 'content', 'created_time'])->offset($offset)->limit($length)->orderByDesc('reply_count')->get()->toArray();

        $userIds = array_column($list, 'user_id');
        $users = User::select(['id', 'nickname', 'avatar'])->whereIn('id', $userIds)->get()->toArray();
        $users = array_combine(
            array_column($users, 'id'),
            array_values($users)
        );

        $subjectIds = array_column($list, 'id');
        $replies = SubjectReply::select(['comment_id', 'user_id', 'reply_user_id', 'content', 'created_time'])->whereIn('comment_id', $subjectIds)->orderBy('created_time')->get()->toArray();

        $replyUserIds = array_merge(array_column($replies, 'user_id') ?? [], array_column($replies, 'reply_user_id') ?? []);
        $replyUsers = User::select(['id', 'nickname', 'avatar'])->whereIn('id', $replyUserIds)->get()->toArray();
        $replyUsers = array_combine(
            array_column($replyUsers, 'id'),
            array_values($replyUsers)
        );

        foreach ($list as $key=>$item) {
            $list[$key]['user_info'] = $users[$item['user_id']];

            foreach ($replies as $reply) {
                if ($reply['comment_id'] == $item['id']) {
                    $list[$key]['replies'][] = [
                        'user_info' => $replyUsers[$reply['user_id']],
                        'reply_user_info' => $replyUsers[$reply['reply_user_id']] ?? [],
                        'content' => $reply['content'],
                        'created_time' => $reply['created_time']
                    ];
                }

            }
        }

        return Page::wrap($count, $page, $length, $list);
    }

    public static function reply($commentId, $content)
    {
        $comment = SubjectComment::find($commentId);

        SubjectReply::insert([
            'user_id' => get_user_id(),
            'reply_user_id' => $comment['user_id'],
            'comment_id' => $commentId,
            'content' => $content,
            'created_time' => date('Y-m-d H:i:s')
        ]);
    }

    public static function dropComment($commentId)
    {
        $comment = SubjectComment::find($commentId);
        $comment->delete();

        Subject::where('id', $comment['id'])->decrement('comment_count');
    }

    public static function like($subjectId)
    {
        SubjectLike::insert([
            'user_id' => get_user_id(),
            'subject_id' => $subjectId,
            'created_time' => date('Y-m-d H:i:s')
        ]);

        Subject::where('id', $subjectId)->increment('good_count');
    }

    public static function likeUserList($page, $length = 10, $subjectId)
    {
        $offset = ($page - 1) * $length;
        $query = SubjectLike::where('subject_id', $subjectId);

        $totalCount = (clone $query)->count();
        $likes = $query->offset($offset)->limit($length)->get()->toArray();

        $likes = array_combine(
            array_column($likes, 'user_id'),
            array_values($likes)
        );

        $userIds = array_column($likes, 'user_id');
        $users = User::select(['id', 'nickname', 'avatar'])->whereIn('id', $userIds)->get()->toArray();

        foreach ($users as $key=>$user) {
            $users[$key]['like_time'] = $likes[$user['id']]['created_time'];
        }

        return Page::wrap($totalCount, $page, $length, $users);
    }

    public static function unlike($subjectId)
    {
        SubjectLike::where('user_id', get_user_id())->where('subject_id', $subjectId)->delete();

        Subject::where('id', $subjectId)->decrement('good_count');
    }

    public static function surnameList($page, $length)
    {
        $surname = UserService::getSurname();
        $offset = ($page - 1) * $length;

        $query = Db::table('wa_subjects', 's')
            ->select(['u.id', 'u.avatar', 'u.nickname', 'u.level', 'u.is_identify', 'up.name', 'up.mobile', Db::raw('s.id as subject_id'), 's.title', 's.content', 's.comment_count', 's.good_count', 's.created_time'])
            ->join(Db::raw('wa_users as u'), 's.user_id', '=', 'u.id', 'left')
            ->join(Db::raw('wa_user_profiles as up'), 's.user_id', '=', 'up.user_id', 'left')
            ->where('u.surname', $surname)
            ->where('is_enable', 1);

        $count = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->get()->toArray();

        $userLevels = UserLevel::list();
        $userLevels = array_combine(
            array_column($userLevels, 'value'),
            array_column($userLevels, 'name')
        );

        $subjectIds = array_column($list, 'subject_id');
        $subjectLikes = SubjectLike::whereIn('subject_id', $subjectIds)->where('user_id', get_user_id())->get()->toArray();
        $subjectLikes = array_combine(
            array_column($subjectLikes, 'subject_id'),
            array_values($subjectLikes)
        );

        $subjectImages = SubjectImage::whereIn('subject_id', $subjectIds)->get()->toArray();

        foreach ($list as $key=>$item) {
            $item = json_decode(json_encode($item), true);
            $item['level_text'] = $userLevels[$item['level']];
            $item['is_like'] = isset($subjectLikes[$item['subject_id']]);

            $item['images'] = [];
            foreach ($subjectImages as $image) {
                if ($item['subject_id'] == $image['subject_id']) {
                    $item['images'][] = full_url($image['img_url']);
                }
            }

            $list[$key] = $item;
        }

        return Page::wrap($count, $page, $length, $list);
    }

    public static function likes($page, $length)
    {
        $offset = ($page - 1) * $length;
        $query = Db::table('wa_subject_likes', 'sl')
            ->select(['u.nickname', 'u.avatar', 'sl.created_time', 's.title', 's.content', 's.id'])
            ->join(Db::raw('wa_subjects as s'), 'sl.subject_id', '=', 's.id', 'left')
            ->join(Db::raw('wa_users as u'), 'u.id', '=', 'sl.user_id', 'left')
            ->where('sl.user_id', get_user_id());

        $count = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->get()->toArray();

        $subjectIds = array_column($list, 'id');
        $subjectImages = SubjectImage::whereIn('subject_id', $subjectIds)->get()->toArray();

        foreach ($list as $key=>$item) {
            $item = json_decode(json_encode($item), true);
            $item['images'] = [];

            foreach ($subjectImages as $image) {
                if ($image['subject_id'] == $item['id']) {
                    $item['images'][] = full_url($image['img_url']);
                }
            }
            $list[$key] = $item;
        }

        return Page::wrap($count, $page, $length, $list);
    }

    public static function comments($page, $length)
    {
        $offset = ($page - 1) * $length;
        $query = Db::table('wa_subject_comments', 'sc')
            ->select(['u.nickname', 'u.avatar', 'sc.content', 'sc.created_time', 's.title', 's.id', Db::raw('sc.id as comment_id')])
            ->join(Db::raw('wa_subjects as s'), 'sc.subject_id', '=', 's.id', 'left')
            ->join(Db::raw('wa_users as u'), 'u.id', '=', 'sc.user_id', 'left')
            ->where('sc.user_id', get_user_id());

        $count = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->get()->toArray();

        $subjectIds = array_column($list, 'id');
        $subjectImages = SubjectImage::whereIn('subject_id', $subjectIds)->get()->toArray();

        $commentIds = array_column($list, 'comment_id');
        $subjectReplies = SubjectReply::whereIn('comment_id', $commentIds)->get()->toArray();

        $userIds = array_merge(array_column($subjectReplies, 'user_id'), array_column($subjectReplies, 'reply_user_id'));
        $users = User::select(['id', 'nickname', 'avatar'])->whereIn('id', $userIds)->get()->toArray();
        $users = array_combine(
            array_column($users, 'id'),
            array_values($users)
        );

        foreach ($list as $key=>$item) {

            $item = json_decode(json_encode($item), true);
            $item['images'] = [];

            foreach ($subjectImages as $image) {
                if ($image['subject_id'] == $item['id']) {
                    $item['images'][] = full_url($image['img_url']);
                }
            }

            $replies = SubjectReply::where('comment_id', $item['comment_id'])->orderByDesc('created_time')->get()->toArray();
            foreach ($replies as $reply) {
                $item['replies'][] = [
                    'user_nickname' => $users[$reply['user_id']]['nickname'],
                    'reply_user_nickname' => $users[$reply['reply_user_id']]['nickname'],
                    'content' => $reply['content']
                ];
            }

            $list[$key] = $item;
        }

        return Page::wrap($count, $page, $length, $list);
    }
}